// scoped_allocator C++11 header
#pragma once
#ifndef _SCOPED_ALLOCATOR_
#define _SCOPED_ALLOCATOR_
#ifndef RC_INVOKED
#include <tuple>
#include <xmemory0>

 #pragma pack(push,_CRT_PACKING)
 #pragma warning(push,3)
 #pragma push_macro("new")
 #undef new

_STD_BEGIN
template<class _Outer,
	class... _Inner>
	class scoped_allocator_adaptor;

		// TEMPLATE STRUCT _Scoped_propagate_on_container_copy

template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_copy
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_copy_assignment
	typedef typename _If<_STD allocator_traits<_Outer>
		::propagate_on_container_copy_assignment::value,
		true_type,
		_Scoped_propagate_on_container_copy<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_copy<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_copy_assignment
	typedef typename _STD allocator_traits<_Outer>
		::propagate_on_container_copy_assignment::type type;
	};

		// TEMPLATE STRUCT _Scoped_propagate_on_container_move
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_move
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_move_assignment
	typedef typename _If<_STD allocator_traits<_Outer>
		::propagate_on_container_move_assignment::value,
		true_type,
		_Scoped_propagate_on_container_move<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_move<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_move_assignment
	typedef typename _STD allocator_traits<_Outer>
		::propagate_on_container_move_assignment::type type;
	};

		// TEMPLATE STRUCT _Scoped_propagate_on_container_swap
template<class _Outer,
	class... _Inner>
	struct _Scoped_propagate_on_container_swap
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_swap
	typedef typename _If<_STD allocator_traits<_Outer>
		::propagate_on_container_swap::value,
		true_type,
		_Scoped_propagate_on_container_swap<_Inner...> >::type
			::type type;
	};

template<class _Outer>
	struct _Scoped_propagate_on_container_swap<_Outer>
	{	// determines scoped_allocator_adaptor<_Outer, _Inner...>
		// ::propagate_on_container_swap
	typedef typename _STD allocator_traits<_Outer>
		::propagate_on_container_swap::type type;
	};

		// TEMPLATE STRUCT _Scoped_outermost_allocator
template<class _Outer>
	struct _Scoped_outermost_allocator
	{	// chooses outermost x.outer_allocator() or x
	template<class _Xouter>
		static auto _Fn(int, _Xouter& _Alval)
			-> decltype(_Alval.outer_allocator())
		{	// returned nested allocator argument
		return (_Alval.outer_allocator());
		}

	template<class _Xouter>
		static auto _Fn(_Wrap_int, _Xouter& _Alval)
			-> _Xouter&
		{	// returned allocator argument
		return (_Alval);
		}

	static _Outer _Outer_obj;

	typedef typename remove_reference<
		decltype(_Fn<_Outer>(0, _Outer_obj))>::type type;
	};

		// TEMPLATE FUNCTION _Scoped_construct
template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types,
	class _Dont_care>
	void _Scoped_construct(_Outermost, _Inner,
		false_type, _Dont_care,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, no allocator
	::new (_Ptr) _Ty(_STD forward<_Types>(_Args)...);
	}

template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types>
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval,
		true_type, false_type,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, leading allocator
	allocator_traits<_Outermost>::construct(_Alval, _Ptr,
		allocator_arg, _Inner_alval,
			_STD forward<_Types>(_Args)...);
	}

template<class _Outermost,
	class _Inner,
	class _Ty,
	class... _Types>
	void _Scoped_construct(_Outermost _Alval, _Inner _Inner_alval,
		true_type, true_type,
		_Ty *_Ptr, _Types&&... _Args)
	{	// construct with optional arguments, trailing allocator
	allocator_traits<_Outermost>::construct(_Alval, _Ptr,
		_STD forward<_Types>(_Args)...,
			_Inner_alval);
	}

		// TEMPLATE FUNCTION _Scoped_construct_tuple
template<class _Alloc,
	class _Ty,
	class... _Atypes,
	class _Dont_care>
	tuple<_Atypes...>
		_Scoped_construct_tuple(_Alloc&, false_type, _Dont_care,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, no allocator
	return (_Val);
	}

template<class _Alloc,
	class _Ty,
	class... _Atypes>
	tuple<allocator_arg_t, _Alloc&, _Atypes...>
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, false_type,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, leading allocator
	return (tuple_cat(tuple<allocator_arg_t, _Alloc&>(
		_Tuple_alloc, _Alty), _Val));
	}

template<class _Alloc,
	class _Ty,
	class... _Atypes>
	tuple<_Atypes..., _Alloc&>
		_Scoped_construct_tuple(_Alloc& _Alty, true_type, true_type,
			tuple<_Atypes...> _Val)
	{	// construct tuple from tuple argument, trailing allocator
	return (tuple_cat(_Val,
		tuple<_Alloc&>(_Alty)));
	}

		// TEMPLATE FUNCTION _Scoped_construct_pair
template<class _Inner,
	class _Ty1,
	class _Ty2,
	class... _Uy1,
	class... _Uy2>
	void _Scoped_construct_pair(_Inner _Inner_alval,
		pair<_Ty1, _Ty2> *_Ptr,
		tuple<_Uy1...> _Val1, tuple<_Uy2...> _Val2)
	{	// construct pair from tuples
	::new (_Ptr) pair<_Ty1, _Ty2>(piecewise_construct,
		_Scoped_construct_tuple<_Inner, _Ty1, _Uy1...>(
			_Inner_alval,
			uses_allocator<_Ty1, _Inner>(),
			is_constructible<_Ty1, _Uy1..., _Inner>(),
			_Val1),
		_Scoped_construct_tuple<_Inner, _Ty2, _Uy2...>(
			_Inner_alval,
			uses_allocator<_Ty2, _Inner>(),
			is_constructible<_Ty2, _Uy2..., _Inner>(),
			_Val2));
	}

		// TEMPLATE CLASS _Scoped_base
template<class _Outer,
	class... _Inner>
	struct _Scoped_base;

template<class _Outer,
	class _Inner0,
	class... _Inner>
	struct _Scoped_base<_Outer, _Inner0, _Inner...>
		: public _Outer
	{	// nest of allocators, arbitrary depth
	typedef scoped_allocator_adaptor<_Outer, _Inner0, _Inner...>
		_Myadaptor;
	typedef scoped_allocator_adaptor<_Inner0, _Inner...>
		inner_allocator_type;

	inner_allocator_type _Inner_obj;

	inner_allocator_type& _Get_inner_object(
		_Myadaptor&)
		{	// return _Inner_obj as inner_object
		return (_Inner_obj);
		}

	const inner_allocator_type& _Get_inner_object(
		const _Myadaptor&) const
		{	// return _Inner_obj as inner_object
		return (_Inner_obj);
		}

	_Scoped_base()
		{	// default construct
		}

	template<class _Other1,
		class _Other2>
		_Scoped_base(_Other1&& _Outer_arg,
			_Other2&& _Inner_arg)
		: _Inner_obj(_STD forward<_Other2>(_Inner_arg))
		{	// construct from (outer, inner)
		(_Outer&)*this = _STD forward<_Other1>(_Outer_arg);
		}

	template<class _Other>
		void operator=(
			scoped_allocator_adaptor<_Other, _Inner0, _Inner...>&&
				_Right)
		{	// move from adaptor<_Other, _Inner0, _Inner...>
		(_Outer&)*this = _STD forward<_Other>(_Right);
		_Inner_obj = _STD forward<inner_allocator_type>(_Right._Inner_obj);
		}

	template<class _Other>
		void operator=(
			const scoped_allocator_adaptor<_Other, _Inner0, _Inner...>&
				_Right)
		{	// assign from adaptor<_Other, _Inner0, _Inner...>
		(_Outer&)*this = (_Other&)_Right;
		_Inner_obj = _Right._Inner_obj;
		}

	_Myadaptor select_on_container_copy_construction() const
		{	// make new adaptor
		return (_Myadaptor(allocator_traits<_Outer>
			::select_on_container_copy_construction(*this),
			_Inner_obj.select_on_container_copy_construction()));
		}
	};

template<class _Outer>
	struct _Scoped_base<_Outer>
		: public _Outer
	{	// nest of allocators, one deep
	typedef scoped_allocator_adaptor<_Outer> _Myadaptor;
	typedef scoped_allocator_adaptor<_Outer> inner_allocator_type;

	inner_allocator_type& _Get_inner_object(
		_Myadaptor& _Self)
		{	// return self as inner_object
		return (_Self);
		}

	const inner_allocator_type& _Get_inner_object(
		const _Myadaptor& _Self) const
		{	// return self as inner_object
		return (_Self);
		}

	_Scoped_base()
		{	// default construct
		}

	template<class _Other1,
		class _Other2>
		_Scoped_base(_Other1&& _Outer_arg,
			_Other2&&)
		: _Outer(_STD forward<_Other1>(_Outer_arg))
		{	// construct from (outer, inner)
		}

	template<class _Other>
		void operator=(scoped_allocator_adaptor<_Other>&& _Right)
		{	// move from adaptor<_Other>
		(_Outer&)*this = _STD forward<_Other>((_Other&)_Right);
		}

	template<class _Other>
		void operator=(const scoped_allocator_adaptor<_Other>& _Right)
		{	// assign from adaptor<_Other>
		(_Outer&)*this = (_Other&)_Right;
		}

	_Myadaptor select_on_container_copy_construction() const
		{	// make new adaptor
		return (_Myadaptor(allocator_traits<_Outer>
			::select_on_container_copy_construction(*this)));
		}
	};

		// TEMPLATE CLASS scoped_allocator_adaptor
template<class _Outer,
	class... _Inner>
	class scoped_allocator_adaptor
		: public _Scoped_base<_Outer, _Inner...>
	{	// nest of allocators
	typedef _Scoped_base<_Outer, _Inner...> _Mybase;
	typedef allocator_traits<_Outer> _Outer_traits;
	typedef typename _Scoped_outermost_allocator<_Outer>::type _Outermost;
	typedef allocator_traits<_Outermost> _Outermost_traits;

public:
	typedef _Outer outer_allocator_type;
	typedef typename _Mybase::inner_allocator_type inner_allocator_type;

	typedef typename _Outer_traits::value_type value_type;
	typedef typename _Outer_traits::pointer pointer;
	typedef typename _Outer_traits::const_pointer const_pointer;
	typedef typename _Outer_traits::void_pointer void_pointer;
	typedef typename _Outer_traits::const_void_pointer const_void_pointer;

	typedef typename _Outer_traits::size_type size_type;
	typedef typename _Outer_traits::difference_type difference_type;

	template<class _Other>
		struct rebind
		{	// converts X<value_type> to X<_Other>
		typedef typename _Get_rebind_type<_Outer, _Other>::type _Other_alloc;
		typedef scoped_allocator_adaptor<_Other_alloc, _Inner...> other;
		};

	typedef typename
		_Scoped_propagate_on_container_copy<_Outermost, _Inner...>::type
			propagate_on_container_copy_assignment;
	typedef typename
		_Scoped_propagate_on_container_move<_Outermost, _Inner...>::type
			propagate_on_container_move_assignment;
	typedef typename
		_Scoped_propagate_on_container_swap<_Outermost, _Inner...>::type
			propagate_on_container_swap;

	outer_allocator_type& outer_allocator() _NOEXCEPT
		{	// get reference to outer allocator
		return (static_cast<_Outer&>(*this));
		}

	const outer_allocator_type& outer_allocator() const _NOEXCEPT
		{	// get reference to outer allocator
		return (static_cast<const _Outer&>(*this));
		}

	inner_allocator_type& inner_allocator() _NOEXCEPT
		{	// get reference to inner allocator
		return (const_cast<inner_allocator_type&>(
			this->_Get_inner_object(*this)));
		}

	const inner_allocator_type& inner_allocator() const _NOEXCEPT
		{	// get reference to inner allocator
		return (this->_Get_inner_object(*this));
		}

	scoped_allocator_adaptor()
		{	// default construct
		}

	scoped_allocator_adaptor(const scoped_allocator_adaptor& _Right) _NOEXCEPT
		: _Mybase(_Right.outer_allocator(),
			_Right.inner_allocator())
		{	// construct from _Right
		}

	template<class _Other>
		scoped_allocator_adaptor(_Other&& _Other_arg,
			const _Inner&... _Inner_arg) _NOEXCEPT
		: _Mybase(_STD forward<_Other>(_Other_arg),
			_STD forward<inner_allocator_type>(
				inner_allocator_type(_Inner_arg...)))
		{	// construct from (_Other, _Inner...)
		}

	template<class _Other>
		scoped_allocator_adaptor(const scoped_allocator_adaptor<_Other,
			_Inner...>& _Right) _NOEXCEPT
		: _Mybase(_Right.outer_allocator(),
			_Right.inner_allocator())
		{	// construct from const adaptor<_Other, _Inner...>&
		}

	template<class _Other>
		scoped_allocator_adaptor(scoped_allocator_adaptor<_Other,
			_Inner...>&& _Right) _NOEXCEPT
		: _Mybase(_STD forward<_Other>(_Right.outer_allocator()),
			_Right.inner_allocator())
		{	// construct from adaptor<_Other, _Inner...>&&
		}

	template<class _Other>
		scoped_allocator_adaptor& operator=(
			scoped_allocator_adaptor<_Other, _Inner...>&& _Right)
		{	// assign from adaptor<_Other, _Inner...>&&
		_Mybase::operator=(_STD forward<_Other>(_Right));
		return (*this);
		}

	template<class _Other>
		scoped_allocator_adaptor& operator=(
			const scoped_allocator_adaptor<_Other, _Inner...>& _Right)
		{	// assign from adaptor<_Other, _Inner...>&
		_Mybase::operator=(_Right);
		return (*this);
		}

	pointer allocate(size_type _Count)
		{	// allocate array of _Count elements, ignore hint
		return (_Outer_traits::allocate(outer_allocator(),
			_Count));
		}

	pointer allocate(size_type _Count, const_void_pointer _Hint)
		{	// allocate array of _Count elements, with hint
		return (_Outer_traits::allocate(outer_allocator(),
			_Count, _Hint));
		}

	void deallocate(pointer _Ptr, size_type _Count)
		{	// deallocate object at _Ptr, with size
		return (_Outer_traits::deallocate(outer_allocator(),
			_Ptr, _Count));
		}

	size_type max_size() const
		{	// estimate maximum array size
		return (_Outer_traits::max_size(outer_allocator()));
		}

	template<class _Ty,
		class... _Types>
		void construct(_Ty *_Ptr, _Types&&... _Args)
		{	// construct with varying allocator styles
		_Scoped_construct(
			_Scoped_outermost_allocator<_Outer>::_Fn(0, *this),
			inner_allocator(),
			uses_allocator<_Ty, inner_allocator_type>(),
			is_constructible<_Ty, _Types..., inner_allocator_type>(),
			_Ptr, _STD forward<_Types>(_Args)...);
		}

	template<class _Ty>
		void destroy(_Ty *_Ptr)
		{	// destroy object at _Ptr
		_Outermost _Alval(_Scoped_outermost_allocator<_Outer>::_Fn(0, *this));
		_Outermost_traits::destroy(_Alval, _Ptr);
		}

		// CONSTRUCT A PAIR
	template<class _Ty1,
		class _Ty2,
		class _Tpl1,
		class _Tpl2>
		void construct(pair<_Ty1, _Ty2> *_Ptr, piecewise_construct_t,
			_Tpl1 _Val1, _Tpl2 _Val2)
		{	// construct pair from tuples
		_Scoped_construct_pair(inner_allocator(), _Ptr, _Val1, _Val2);
		}

	template<class _Ty1,
		class _Ty2>
		void construct(pair<_Ty1, _Ty2> *_Ptr)
		{	// construct pair from pointer to other pair
		this->construct(_Ptr, piecewise_construct,
			tuple<>(),
			tuple<>());
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			_Uy1&& _Val1, _Uy2&& _Val2)
		{	// construct pair from two movable values
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_STD forward<_Uy1>(_Val1)),
			forward_as_tuple(_STD forward<_Uy2>(_Val2)));
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			const pair<_Uy1, _Uy2>& _Other)
		{	// construct pair from copyable pair
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_Other.first),
			forward_as_tuple(_Other.second));
		}

	template<class _Ty1,
		class _Ty2,
		class _Uy1,
		class _Uy2>
		void construct(pair<_Ty1, _Ty2> *_Ptr,
			pair<_Uy1, _Uy2>&& _Other)
		{	// construct pair from movable pair
		this->construct(_Ptr, piecewise_construct,
			forward_as_tuple(_STD forward<_Uy1>(_Other.first)),
			forward_as_tuple(_STD forward<_Uy2>(_Other.second)));
		}
	};

template<class _Outer1,
	class _Outer2,
	class _Inner1,
	class... _Inner> inline
	bool operator==(
		const scoped_allocator_adaptor<_Outer1, _Inner1, _Inner...>& _Left,
		const scoped_allocator_adaptor<_Outer2, _Inner1, _Inner...>& _Right)
			_NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (_Left.outer_allocator() == _Right.outer_allocator()
			&& _Left.inner_allocator() == _Right.inner_allocator());
		}

template<class _Outer1,
	class _Outer2> inline
	bool operator==(
		const scoped_allocator_adaptor<_Outer1>& _Left,
		const scoped_allocator_adaptor<_Outer2>& _Right) _NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (_Left.outer_allocator() == _Right.outer_allocator());
		}

template<class _Outer1,
	class _Outer2,
	class... _Inner> inline
	bool operator!=(
		const scoped_allocator_adaptor<_Outer1, _Inner...>& _Left,
		const scoped_allocator_adaptor<_Outer2, _Inner...>& _Right) _NOEXCEPT
		{	// compare scoped_allocator_adaptors for equality
		return (!(_Left == _Right));
		}

_STD_END
 #pragma pop_macro("new")
 #pragma warning(pop)
 #pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _SCOPED_ALLOCATOR_ */

/*
 * Copyright (c) 1992-2012 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
V6.00:0009 */
